﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Kaleta.Network;
using Lidgren.Network;
using System.Threading;
using System.Diagnostics;
using Kaleta.Network.Serialization.Types;

namespace SimpleCharServerClient
{
    public partial class Form1 : Form
    {
        private AutoResetEvent autoEvent;

        public Form1()
        {
            InitializeComponent();

            //autoEvent = new AutoResetEvent(false);
            //TimerCallback timerDelegate = new TimerCallback(UpdateNetwork);

            //System.Threading.Timer stateTimer =
            //        new System.Threading.Timer(timerDelegate, autoEvent, 50, 50);

            
        }

        public void OnAppIdle(object sender, EventArgs e)
        {
            UpdateNetwork(null);

            foreach (var obj in DistributionSession.DistributableObjects.Values)
            {
                Chatter chat = obj as Chatter;
                if (chat != null && chat.HasNewMessage == true)
                {
                    this.listBox1.Items.Add("From " + chat.Creator.ToString() + ": " + chat.Message);
                    this.listBox1.SetSelected(this.listBox1.Items.Count-1, true);
                    this.listBox1.Refresh();
                    this.Refresh();

                    chat.HasNewMessage = false;
                }
            }
        }

        private void button1_Click(object sender, EventArgs e)
        {
            CreateServer();
        }

        private void button2_Click(object sender, EventArgs e)
        {
            CreateClient();
        }

        private void UpdateNetwork(Object stateInfo)
        {
            if (DistributionSession.Server != null)
                DistributionSession.ServerUpdate();

            if (DistributionSession.Client != null)
                DistributionSession.ClientUpdate();
        }

        private void CreateServer()
        {
            if (DistributionSession.Server != null) return;

            NetConfiguration serverConfig = new NetConfiguration(this.GetType().Name);
            serverConfig.Port = 666;
            serverConfig.MaxConnections = 4;
            NetServer server = new NetServer(serverConfig);
            server.Start();

            Debug.WriteLine("Server: started");

            DistributionSession.Initialize(server,
                new Type[] { typeof(Chatter) });
        }

        private void CreateClient()
        {
            if (DistributionSession.Client != null) return;

            NetConfiguration clientConfig = new NetConfiguration(this.GetType().Name);
            NetClient client = new NetClient(clientConfig);
            client.Start();

            Debug.WriteLine("Client: started");

            client.DiscoverKnownServer("localhost", 666);

            DistributionSession.Initialize(client,
                new Type[] { typeof(Chatter) });

            DistributionSession.ServerDataRecieved += new EventHandler<NetworkDataRecievedEventArgs>(DistributionSession_ServerDataRecieved);
        }

        void DistributionSession_ServerDataRecieved(object sender, NetworkDataRecievedEventArgs e)
        {
            lock (this)
            {
                if (e.NetMessageType == NetMessageType.ServerDiscovered)
                {
                    Debug.WriteLine("Client: Connecting..");
                    DistributionSession.Client.Connect(e.ReadBuffer.ReadIPEndPoint());
                }

                else if (e.NetMessageType == NetMessageType.ServerDiscovered)
                    Debug.WriteLine("Client: Server discovered");

                else if (DistributionSession.Client.Status == NetConnectionStatus.Connected)
                {
                    if (localChatter == null)
                    {
                        localChatter = new Chatter();
                        DistributionSession.DistributeObject(localChatter);
                        localChatter.Creator = new DistributableString("Guest["+localChatter.Key.ToString()+"]");

                        Debug.WriteLine("Client connected. Creating chatter. Creator=Guest["+ localChatter.Key.ToString()+"]");
                    }
                }

                else
                    Debug.WriteLine("Client status: " + DistributionSession.Client.Status.ToString() + " NetMsgType: " +
                                    e.NetMessageType);
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            string message = this.textBox1.Text;
            if (this.localChatter == null)
                this.listBox1.Items.Add("Not connected to server!");
            else
                this.localChatter.Message = new DistributableString(message);
        }

        private Chatter localChatter;
    }
}
